<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Tutorial 25: Xml Handling</title>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Wanted to avoid copying .css to each folder, so copied default .css from doxyen in here, kicked out most stuff we don't need for examples and modified some a little bit. 
     Target was having a single html in each example folder which is created from the main.cpp files and needs no files besides some images below media folder.
     Feel free to improve :)
	 -->
<style>
body, table, div, p, dl {
	font: 400 14px/22px;
}
body {
	background-color: #F0F0F0;
	color: black;
	margin-left: 5%;
	margin-right: 5%;
}
p.reference, p.definition {
	font: 400 14px/22px;
}
.title {
	font: 400 14px/28px;
	font-size: 150%;
	font-weight: bold;
	margin: 10px 2px;
}
h1, h2, h3, h4, h5, h6 {
	-webkit-transition: text-shadow 0.5s linear;
	-moz-transition: text-shadow 0.5s linear;
	-ms-transition: text-shadow 0.5s linear;
	-o-transition: text-shadow 0.5s linear;
	transition: text-shadow 0.5s linear;
	margin-right: 15px;
}
caption {
	font-weight: bold;
}
h3.version {
	font-size: 90%;
	text-align: center;
}
a {
	color: #3D578C;
	font-weight: normal;
	text-decoration: none;
}
.contents a:visited {
	color: #4665A2;
}
a:hover {
	text-decoration: underline;
}
a.el {
	font-weight: bold;
}
a.code, a.code:visited, a.line, a.line:visited {
	color: #4665A2; 
}
a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
	color: #4665A2; 
}
pre.fragment {
	border: 1px solid #C4CFE5;
	background-color: #FBFCFD;
	padding: 4px 6px;
	margin: 4px 8px 4px 2px;
	overflow: auto;
	word-wrap: break-word;
	font-size:  9pt;
	line-height: 125%;
	font-family: monospace, fixed;
	font-size: 105%;
}
div.fragment {
	padding: 0px;
	margin: 4px 8px 4px 2px;
	background-color: #FBFCFD;
	border: 1px solid #C4CFE5;
}
div.line {
	font-family: monospace, fixed;
	font-size: 13px;
	min-height: 13px;
	line-height: 1.0;
	text-wrap: unrestricted;
	white-space: -moz-pre-wrap; /* Moz */
	white-space: -pre-wrap;     /* Opera 4-6 */
	white-space: -o-pre-wrap;   /* Opera 7 */
	white-space: pre-wrap;      /* CSS3  */
	word-wrap: break-word;      /* IE 5.5+ */
	text-indent: -53px;
	padding-left: 53px;
	padding-bottom: 0px;
	margin: 0px;
	-webkit-transition-property: background-color, box-shadow;
	-webkit-transition-duration: 0.5s;
	-moz-transition-property: background-color, box-shadow;
	-moz-transition-duration: 0.5s;
	-ms-transition-property: background-color, box-shadow;
	-ms-transition-duration: 0.5s;
	-o-transition-property: background-color, box-shadow;
	-o-transition-duration: 0.5s;
	transition-property: background-color, box-shadow;
	transition-duration: 0.5s;
}
div.contents {
	margin-top: 10px;
	margin-left: 12px;
	margin-right: 8px;
}
div.center {
	text-align: center;
	margin-top: 0px;
	margin-bottom: 0px;
	padding: 0px;
}
div.center img {
	border: 0px;
}
span.keyword {
	color: #008000
}
span.keywordtype {
	color: #604020
}
span.keywordflow {
	color: #e08000
}
span.comment {
	color: #800000
}
span.preprocessor {
	color: #806020
}
span.stringliteral {
	color: #002080
}
span.charliteral {
	color: #008080
}
blockquote {
	background-color: #F7F8FB;
	border-left: 2px solid #9CAFD4;
	margin: 0 24px 0 4px;
	padding: 0 12px 0 16px;
}
hr {
	height: 0px;
	border: none;
	border-top: 1px solid #4A6AAA;
}
address {
	font-style: normal;
	color: #2A3D61;
}
div.header {
	background-image:url('nav_h.png');
	background-repeat:repeat-x;
	background-color: #F9FAFC;
	margin:  0px;
	border-bottom: 1px solid #C4CFE5;
}
div.headertitle {
	padding: 5px 5px 5px 10px;
}
.image {
	text-align: center;
}
.caption {
	font-weight: bold;
}
div.zoom {
	border: 1px solid #90A5CE;
}
tr.heading h2 {
	margin-top: 12px;
	margin-bottom: 4px;
}
</style>
</head>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<!--END TITLEAREA-->
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Tutorial 25: Xml Handling </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><div class="image">
<img src="../../media/example_screenshots/025shot.jpg" alt="025shot.jpg"/>
</div>
 <p>Demonstrates loading and saving of configurations via XML</p>
<dl class="section author"><dt>Author</dt><dd>Y.M. Bosman &lt;<a href="#" onclick="location.href='mai'+'lto:'+'yor'+'an'+'.bo'+'sm'+'an@'+'gm'+'ail'+'.c'+'om'; return false;">yoran<span style="display: none;">.nosp@m.</span>.bos<span style="display: none;">.nosp@m.</span>man@g<span style="display: none;">.nosp@m.</span>mail<span style="display: none;">.nosp@m.</span>.com</a>&gt;</dd></dl>
<p>This demo features a fully usable system for configuration handling. The code can easily be integrated into own apps.</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;irrlicht.h&gt;</span></div><div class="line"><span class="preprocessor">#include &quot;exampleHelper.h&quot;</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span>irr;</div><div class="line"><span class="keyword">using namespace </span>core;</div><div class="line"><span class="keyword">using namespace </span>scene;</div><div class="line"><span class="keyword">using namespace </span>video;</div><div class="line"><span class="keyword">using namespace </span>io;</div><div class="line"><span class="keyword">using namespace </span>gui;</div><div class="line"></div><div class="line"><span class="preprocessor">#ifdef _MSC_VER</span></div><div class="line"><span class="preprocessor">#pragma comment(lib, &quot;Irrlicht.lib&quot;)</span></div><div class="line"><span class="preprocessor">#endif</span></div></div><!-- fragment --><p> SettingManager class.</p>
<p>This class loads and writes the settings and manages the options.</p>
<p>The class makes use of irrMap which is a an associative arrays using a red-black tree it allows easy mapping of a key to a value, along the way there is some information on how to use it. </p><div class="fragment"><div class="line"><span class="keyword">class </span>SettingManager</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"></div><div class="line">    <span class="comment">// Construct setting managers and set default settings</span></div><div class="line">    SettingManager(<span class="keyword">const</span> stringw&amp; settings_file): SettingsFile(settings_file), NullDevice(0)</div><div class="line">    {</div><div class="line">        <span class="comment">// Irrlicht null device, we want to load settings before we actually created our device, therefore, nulldevice</span></div><div class="line">        NullDevice = irr::createDevice(irr::video::EDT_NULL);</div><div class="line"></div><div class="line">        <span class="comment">//DriverOptions is an irrlicht map,</span></div><div class="line">        <span class="comment">//we can insert values in the map in two ways by calling insert(key,value) or by using the [key] operator</span></div><div class="line">        <span class="comment">//the [] operator overrides values if they already exist</span></div><div class="line">        DriverOptions.insert(L<span class="stringliteral">&quot;Software&quot;</span>, EDT_SOFTWARE);</div><div class="line">        DriverOptions.insert(L<span class="stringliteral">&quot;OpenGL&quot;</span>, EDT_OPENGL);</div><div class="line">        DriverOptions.insert(L<span class="stringliteral">&quot;Direct3D9&quot;</span>, EDT_DIRECT3D9);</div><div class="line"></div><div class="line">        <span class="comment">//some resolution options</span></div><div class="line">        ResolutionOptions.insert(L<span class="stringliteral">&quot;640x480&quot;</span>, dimension2du(640,480));</div><div class="line">        ResolutionOptions.insert(L<span class="stringliteral">&quot;800x600&quot;</span>, dimension2du(800,600));</div><div class="line">        ResolutionOptions.insert(L<span class="stringliteral">&quot;1024x768&quot;</span>, dimension2du(1024,768));</div><div class="line"></div><div class="line">        <span class="comment">//our preferred defaults</span></div><div class="line">        SettingMap.insert(L<span class="stringliteral">&quot;driver&quot;</span>, L<span class="stringliteral">&quot;Direct3D9&quot;</span>);</div><div class="line">        SettingMap.insert(L<span class="stringliteral">&quot;resolution&quot;</span>, L<span class="stringliteral">&quot;640x480&quot;</span>);</div><div class="line">        SettingMap.insert(L<span class="stringliteral">&quot;fullscreen&quot;</span>, L<span class="stringliteral">&quot;0&quot;</span>); <span class="comment">//0 is false</span></div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// Destructor, you could store settings automatically on exit of your</span></div><div class="line">    <span class="comment">// application if you wanted to in our case we simply drop the</span></div><div class="line">    <span class="comment">// nulldevice</span></div><div class="line">    ~SettingManager()</div><div class="line">    {</div><div class="line">        <span class="keywordflow">if</span> (NullDevice)</div><div class="line">        {</div><div class="line">            NullDevice-&gt;closeDevice();</div><div class="line">            NullDevice-&gt;drop();</div><div class="line">        }</div><div class="line">    };</div></div><!-- fragment --><p> Load xml from disk, overwrite default settings The xml we are trying to load has the following structure settings nested in sections nested in the root node, like: </p><pre class="fragment">    &lt;pre&gt;
        &lt;?xml version="1.0"?&gt;
        &lt;mygame&gt;
            &lt;video&gt;
                &lt;setting name="driver" value="Direct3D9" /&gt;
                &lt;setting name="fullscreen" value="0" /&gt;
                &lt;setting name="resolution" value="1024x768" /&gt;
            &lt;/video&gt;
        &lt;/mygame&gt;
    &lt;/pre&gt;</pre> <div class="fragment"><div class="line">    <span class="keywordtype">bool</span> load()</div><div class="line">    {</div><div class="line">        <span class="comment">//if not able to create device don&#39;t attempt to load</span></div><div class="line">        <span class="keywordflow">if</span> (!NullDevice)</div><div class="line">            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"></div><div class="line">        irr::io::IXMLReader* xml = NullDevice-&gt;getFileSystem()-&gt;createXMLReader(SettingsFile);  <span class="comment">//create xml reader</span></div><div class="line">        <span class="keywordflow">if</span> (!xml)</div><div class="line">            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"></div><div class="line">        <span class="keyword">const</span> stringw settingTag(L<span class="stringliteral">&quot;setting&quot;</span>); <span class="comment">//we&#39;ll be looking for this tag in the xml</span></div><div class="line">        stringw currentSection; <span class="comment">//keep track of our current section</span></div><div class="line">        <span class="keyword">const</span> stringw videoTag(L<span class="stringliteral">&quot;video&quot;</span>); <span class="comment">//constant for videotag</span></div><div class="line"></div><div class="line">        <span class="comment">//while there is more to read</span></div><div class="line">        <span class="keywordflow">while</span> (xml-&gt;read())</div><div class="line">        {</div><div class="line">            <span class="comment">//check the node type</span></div><div class="line">            <span class="keywordflow">switch</span> (xml-&gt;getNodeType())</div><div class="line">            {</div><div class="line">                <span class="comment">//we found a new element</span></div><div class="line">                <span class="keywordflow">case</span> irr::io::EXN_ELEMENT:</div><div class="line">                {</div><div class="line">                    <span class="comment">//we currently are in the empty or mygame section and find the video tag so we set our current section to video</span></div><div class="line">                    <span class="keywordflow">if</span> (currentSection.empty() &amp;&amp; videoTag.equals_ignore_case(xml-&gt;getNodeName()))</div><div class="line">                    {</div><div class="line">                        currentSection = videoTag;</div><div class="line">                    }</div><div class="line">                    <span class="comment">//we are in the video section and we find a setting to parse</span></div><div class="line">                    <span class="keywordflow">else</span> <span class="keywordflow">if</span> (currentSection.equals_ignore_case(videoTag) &amp;&amp; settingTag.equals_ignore_case(xml-&gt;getNodeName() ))</div><div class="line">                    {</div><div class="line">                        <span class="comment">//read in the key</span></div><div class="line">                        stringw key = xml-&gt;getAttributeValueSafe(L<span class="stringliteral">&quot;name&quot;</span>);</div><div class="line">                        <span class="comment">//if there actually is a key to set</span></div><div class="line">                        <span class="keywordflow">if</span> (!key.empty())</div><div class="line">                        {</div><div class="line">                            <span class="comment">//set the setting in the map to the value,</span></div><div class="line">                            <span class="comment">//the [] operator overrides values if they already exist or inserts a new key value</span></div><div class="line">                            <span class="comment">//pair into the settings map if it was not defined yet</span></div><div class="line">                            SettingMap[key] = xml-&gt;getAttributeValueSafe(L<span class="stringliteral">&quot;value&quot;</span>);</div><div class="line">                        }</div><div class="line">                    }</div><div class="line"></div><div class="line">                    <span class="comment">//..</span></div><div class="line">                    <span class="comment">// You can add your own sections and tags to read in here</span></div><div class="line">                    <span class="comment">//..</span></div><div class="line">                }</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">                <span class="comment">//we found the end of an element</span></div><div class="line">                <span class="keywordflow">case</span> irr::io::EXN_ELEMENT_END:</div><div class="line">                    <span class="comment">//we were at the end of the video section so we reset our tag</span></div><div class="line">                    currentSection=L<span class="stringliteral">&quot;&quot;</span>;</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line">                <span class="keywordflow">default</span>:</div><div class="line">                    <span class="keywordflow">break</span>;</div><div class="line">            }</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">// don&#39;t forget to delete the xml reader</span></div><div class="line">        xml-&gt;drop();</div><div class="line"></div><div class="line">        <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// Save the xml to disk. We use the nulldevice.</span></div><div class="line">    <span class="keywordtype">bool</span> save()</div><div class="line">    {</div><div class="line"></div><div class="line">        <span class="comment">//if not able to create device don&#39;t attempt to save</span></div><div class="line">        <span class="keywordflow">if</span> (!NullDevice)</div><div class="line">            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"></div><div class="line">        <span class="comment">//create xml writer</span></div><div class="line">        irr::io::IXMLWriter* xwriter = NullDevice-&gt;getFileSystem()-&gt;createXMLWriter( SettingsFile );</div><div class="line">        <span class="keywordflow">if</span> (!xwriter)</div><div class="line">            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"></div><div class="line">        <span class="comment">//write out the obligatory xml header. Each xml-file needs to have exactly one of those.</span></div><div class="line">        xwriter-&gt;writeXMLHeader();</div><div class="line"></div><div class="line">        <span class="comment">//start element mygame, you replace the label &quot;mygame&quot; with anything you want</span></div><div class="line">        xwriter-&gt;writeElement(L<span class="stringliteral">&quot;mygame&quot;</span>);</div><div class="line">        xwriter-&gt;writeLineBreak();                  <span class="comment">//new line</span></div><div class="line"></div><div class="line">        <span class="comment">//start section with video settings</span></div><div class="line">        xwriter-&gt;writeElement(L<span class="stringliteral">&quot;video&quot;</span>);</div><div class="line">        xwriter-&gt;writeLineBreak();                  <span class="comment">//new line</span></div><div class="line"></div><div class="line">        <span class="comment">// getIterator gets us a pointer to the first node of the settings map</span></div><div class="line">        <span class="comment">// every iteration we increase the iterator which gives us the next map node</span></div><div class="line">        <span class="comment">// until we reach the end we write settings one by one by using the nodes key and value functions</span></div><div class="line">        map&lt;stringw, stringw&gt;::Iterator i = SettingMap.getIterator();</div><div class="line">        <span class="keywordflow">for</span>(; !i.atEnd(); i++)</div><div class="line">        {</div><div class="line">            <span class="comment">//write element as &lt;setting name=&quot;key&quot; value=&quot;x&quot; /&gt;</span></div><div class="line">            <span class="comment">//the second parameter indicates this is an empty element with no children, just attributes</span></div><div class="line">            xwriter-&gt;writeElement(L<span class="stringliteral">&quot;setting&quot;</span>,<span class="keyword">true</span>, L<span class="stringliteral">&quot;name&quot;</span>, i-&gt;getKey().c_str(), L<span class="stringliteral">&quot;value&quot;</span>,i-&gt;getValue().c_str() );</div><div class="line">            xwriter-&gt;writeLineBreak();</div><div class="line">        }</div><div class="line">        xwriter-&gt;writeLineBreak();</div><div class="line"></div><div class="line">        <span class="comment">//close video section</span></div><div class="line">        xwriter-&gt;writeClosingTag(L<span class="stringliteral">&quot;video&quot;</span>);</div><div class="line">        xwriter-&gt;writeLineBreak();</div><div class="line"></div><div class="line">        <span class="comment">//..</span></div><div class="line">        <span class="comment">// You can add writing sound settings, savegame information etc</span></div><div class="line">        <span class="comment">//..</span></div><div class="line"></div><div class="line">        <span class="comment">//close mygame section</span></div><div class="line">        xwriter-&gt;writeClosingTag(L<span class="stringliteral">&quot;mygame&quot;</span>);</div><div class="line"></div><div class="line">        <span class="comment">//delete xml writer</span></div><div class="line">        xwriter-&gt;drop();</div><div class="line"></div><div class="line">        <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// Set setting in our manager</span></div><div class="line">    <span class="keywordtype">void</span> setSetting(<span class="keyword">const</span> stringw&amp; name, <span class="keyword">const</span> stringw&amp; value)</div><div class="line">    {</div><div class="line">        SettingMap[name]=value;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// set setting overload to quickly assign integers to our setting map</span></div><div class="line">    <span class="keywordtype">void</span> setSetting(<span class="keyword">const</span> stringw&amp; name, s32 value)</div><div class="line">    {</div><div class="line">        SettingMap[name]=stringw(value);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// Get setting as string</span></div><div class="line">    stringw getSetting(<span class="keyword">const</span> stringw&amp; key)<span class="keyword"> const</span></div><div class="line"><span class="keyword">    </span>{</div><div class="line">        <span class="comment">//the find function or irrmap returns a pointer to a map Node</span></div><div class="line">        <span class="comment">//if the key can be found, otherwise it returns null</span></div><div class="line">        <span class="comment">//the map node has the function getValue and getKey, as we already know the key, we return node-&gt;getValue()</span></div><div class="line">        map&lt;stringw, stringw&gt;::Node* n = SettingMap.find(key);</div><div class="line">        <span class="keywordflow">if</span> (n)</div><div class="line">            <span class="keywordflow">return</span> n-&gt;getValue();</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">            <span class="keywordflow">return</span> L<span class="stringliteral">&quot;&quot;</span>;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">//</span></div><div class="line">    <span class="keywordtype">bool</span> getSettingAsBoolean(<span class="keyword">const</span> stringw&amp; key )<span class="keyword"> const</span></div><div class="line"><span class="keyword">    </span>{</div><div class="line">        stringw s = getSetting(key);</div><div class="line">        <span class="keywordflow">if</span> (s.empty())</div><div class="line">            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line">        <span class="keywordflow">return</span> s.equals_ignore_case(L<span class="stringliteral">&quot;1&quot;</span>);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">//</span></div><div class="line">    s32 getSettingAsInteger(<span class="keyword">const</span> stringw&amp; key)<span class="keyword"> const</span></div><div class="line"><span class="keyword">    </span>{</div><div class="line">        <span class="comment">//we implicitly cast to string instead of stringw because strtol10 does not accept wide strings</span></div><div class="line">        <span class="keyword">const</span> stringc s = getSetting(key);</div><div class="line">        <span class="keywordflow">if</span> (s.empty())</div><div class="line">            <span class="keywordflow">return</span> 0;</div><div class="line"></div><div class="line">        <span class="keywordflow">return</span> strtol10(s.c_str());</div><div class="line">    }</div><div class="line"></div><div class="line"><span class="keyword">public</span>:</div><div class="line">    map&lt;stringw, s32&gt; DriverOptions; <span class="comment">//available options for driver config</span></div><div class="line">    map&lt;stringw, dimension2du&gt; ResolutionOptions; <span class="comment">//available options for resolution config</span></div><div class="line"><span class="keyword">private</span>:</div><div class="line">    SettingManager(<span class="keyword">const</span> SettingManager&amp; other); <span class="comment">// defined but not implemented</span></div><div class="line">    SettingManager&amp; operator=(<span class="keyword">const</span> SettingManager&amp; other); <span class="comment">// defined but not implemented</span></div><div class="line"></div><div class="line">    map&lt;stringw, stringw&gt; SettingMap; <span class="comment">//current config</span></div><div class="line"></div><div class="line">    stringw SettingsFile; <span class="comment">// location of the xml, usually the</span></div><div class="line">    irr::IrrlichtDevice* NullDevice;</div><div class="line">};</div></div><!-- fragment --><p> Application context for global variables </p><div class="fragment"><div class="line"><span class="keyword">struct </span>SAppContext</div><div class="line">{</div><div class="line">    SAppContext()</div><div class="line">        : Device(0),Gui(0), Driver(0), Settings(0), ShouldQuit(false),</div><div class="line">        ButtonSave(0), ButtonExit(0), ListboxDriver(0),</div><div class="line">        ListboxResolution(0), CheckboxFullscreen(0)</div><div class="line">    {</div><div class="line">    }</div><div class="line"></div><div class="line">    ~SAppContext()</div><div class="line">    {</div><div class="line">        <span class="keywordflow">if</span> (Settings)</div><div class="line">            <span class="keyword">delete</span> Settings;</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (Device)</div><div class="line">        {</div><div class="line">            Device-&gt;closeDevice();</div><div class="line">            Device-&gt;drop();</div><div class="line">        }</div><div class="line">    }</div><div class="line"></div><div class="line">    IrrlichtDevice* Device;</div><div class="line">    IGUIEnvironment* Gui;</div><div class="line">    IVideoDriver* Driver;</div><div class="line">    SettingManager* Settings;</div><div class="line">    <span class="keywordtype">bool</span> ShouldQuit;</div><div class="line"></div><div class="line">    <span class="comment">//settings dialog</span></div><div class="line">    IGUIButton* ButtonSave;</div><div class="line">    IGUIButton* ButtonExit;</div><div class="line">    IGUIListBox* ListboxDriver;</div><div class="line">    IGUIListBox* ListboxResolution;</div><div class="line">    IGUICheckBox* CheckboxFullscreen;</div><div class="line">};</div></div><!-- fragment --><p> A typical event receiver. </p><div class="fragment"><div class="line"><span class="keyword">class </span>MyEventReceiver : <span class="keyword">public</span> IEventReceiver</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line">    MyEventReceiver(SAppContext &amp; a) : App(a) { }</div><div class="line"></div><div class="line">    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> OnEvent(<span class="keyword">const</span> SEvent&amp; event)</div><div class="line">    {</div><div class="line">        <span class="keywordflow">if</span> (event.EventType == EET_GUI_EVENT )</div><div class="line">        {</div><div class="line">            <span class="keywordflow">switch</span> ( event.GUIEvent.EventType )</div><div class="line">            {</div><div class="line">                <span class="comment">//handle button click events</span></div><div class="line">                <span class="keywordflow">case</span> EGET_BUTTON_CLICKED:</div><div class="line">                {</div><div class="line">                    <span class="comment">//Our save button was called so we obtain the settings from our dialog and save them</span></div><div class="line">                    <span class="keywordflow">if</span> ( event.GUIEvent.Caller == App.ButtonSave )</div><div class="line">                    {</div><div class="line">                        <span class="comment">//if there is a selection write it</span></div><div class="line">                        <span class="keywordflow">if</span> ( App.ListboxDriver-&gt;getSelected() != -1)</div><div class="line">                            App.Settings-&gt;setSetting(L<span class="stringliteral">&quot;driver&quot;</span>, App.ListboxDriver-&gt;getListItem(App.ListboxDriver-&gt;getSelected()));</div><div class="line"></div><div class="line">                        <span class="comment">//if there is a selection write it</span></div><div class="line">                        <span class="keywordflow">if</span> ( App.ListboxResolution-&gt;getSelected() != -1)</div><div class="line">                            App.Settings-&gt;setSetting(L<span class="stringliteral">&quot;resolution&quot;</span>, App.ListboxResolution-&gt;getListItem(App.ListboxResolution-&gt;getSelected()));</div><div class="line"></div><div class="line">                        App.Settings-&gt;setSetting(L<span class="stringliteral">&quot;fullscreen&quot;</span>, App.CheckboxFullscreen-&gt;isChecked());</div><div class="line"></div><div class="line"></div><div class="line">                        <span class="keywordflow">if</span> (App.Settings-&gt;save())</div><div class="line">                        {</div><div class="line">                            App.Gui-&gt;addMessageBox(L<span class="stringliteral">&quot;settings save&quot;</span>,L<span class="stringliteral">&quot;settings saved, please restart for settings to change effect&quot;</span>,<span class="stringliteral">&quot;&quot;</span>,<span class="keyword">true</span>);</div><div class="line">                        }</div><div class="line">                    }</div><div class="line">                    <span class="comment">// cancel/exit button clicked, tell the application to exit</span></div><div class="line">                    <span class="keywordflow">else</span> <span class="keywordflow">if</span> ( event.GUIEvent.Caller == App.ButtonExit)</div><div class="line">                    {</div><div class="line">                        App.ShouldQuit = <span class="keyword">true</span>;</div><div class="line">                    }</div><div class="line">                }</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line">                <span class="keywordflow">default</span>:</div><div class="line">                    <span class="keywordflow">break</span>;</div><div class="line">            }</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line">    }</div><div class="line"></div><div class="line"><span class="keyword">private</span>:</div><div class="line">    SAppContext &amp; App;</div><div class="line">};</div></div><!-- fragment --><p> Function to create a video settings dialog This dialog shows the current settings from the configuration xml and allows them to be changed </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> createSettingsDialog(SAppContext&amp; app)</div><div class="line">{</div><div class="line">    <span class="comment">// first get rid of alpha in gui</span></div><div class="line">    <span class="keywordflow">for</span> (irr::s32 i=0; i&lt;irr::gui::EGDC_COUNT ; ++i)</div><div class="line">    {</div><div class="line">        irr::video::SColor col = app.Gui-&gt;getSkin()-&gt;getColor((irr::gui::EGUI_DEFAULT_COLOR)i);</div><div class="line">        col.setAlpha(255);</div><div class="line">        app.Gui-&gt;getSkin()-&gt;setColor((irr::gui::EGUI_DEFAULT_COLOR)i, col);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">//create video settings windows</span></div><div class="line">    gui::IGUIWindow* windowSettings = app.Gui-&gt;addWindow(rect&lt;s32&gt;(10,10,400,400),<span class="keyword">true</span>,L<span class="stringliteral">&quot;Videosettings&quot;</span>);</div><div class="line">    app.Gui-&gt;addStaticText (L<span class="stringliteral">&quot;Select your desired video settings&quot;</span>, rect&lt; s32 &gt;(10,20, 200, 40), <span class="keyword">false</span>, <span class="keyword">true</span>, windowSettings);</div><div class="line"></div><div class="line">    <span class="comment">// add listbox for driver choice</span></div><div class="line">    app.Gui-&gt;addStaticText (L<span class="stringliteral">&quot;Driver&quot;</span>, rect&lt; s32 &gt;(10,50, 200, 60), <span class="keyword">false</span>, <span class="keyword">true</span>, windowSettings);</div><div class="line">    app.ListboxDriver = app.Gui-&gt;addListBox(rect&lt;s32&gt;(10,60,220,120), windowSettings, 1,<span class="keyword">true</span>);</div><div class="line"></div><div class="line">    <span class="comment">//add all available options to the driver choice listbox</span></div><div class="line">    map&lt;stringw, s32&gt;::Iterator i = app.Settings-&gt;DriverOptions.getIterator();</div><div class="line">    <span class="keywordflow">for</span>(; !i.atEnd(); i++)</div><div class="line">        app.ListboxDriver-&gt;addItem(i-&gt;getKey().c_str());</div><div class="line"></div><div class="line">    <span class="comment">//set currently selected driver</span></div><div class="line">    app.ListboxDriver-&gt;setSelected(app.Settings-&gt;getSetting(<span class="stringliteral">&quot;driver&quot;</span>).c_str());</div><div class="line"></div><div class="line">    <span class="comment">// add listbox for resolution choice</span></div><div class="line">    app.Gui-&gt;addStaticText (L<span class="stringliteral">&quot;Resolution&quot;</span>, rect&lt; s32 &gt;(10,130, 200, 140), <span class="keyword">false</span>, <span class="keyword">true</span>, windowSettings);</div><div class="line">    app.ListboxResolution = app.Gui-&gt;addListBox(rect&lt;s32&gt;(10,140,220,200), windowSettings, 1,<span class="keyword">true</span>);</div><div class="line"></div><div class="line">    <span class="comment">//add all available options to the resolution listbox</span></div><div class="line">    map&lt;stringw, dimension2du&gt;::Iterator ri = app.Settings-&gt;ResolutionOptions.getIterator();</div><div class="line">    <span class="keywordflow">for</span>(; !ri.atEnd(); ri++)</div><div class="line">        app.ListboxResolution-&gt;addItem(ri-&gt;getKey().c_str());</div><div class="line"></div><div class="line">    <span class="comment">//set currently selected resolution</span></div><div class="line">    app.ListboxResolution-&gt;setSelected(app.Settings-&gt;getSetting(<span class="stringliteral">&quot;resolution&quot;</span>).c_str());</div><div class="line"></div><div class="line">    <span class="comment">//add checkbox to toggle fullscreen, initially set to loaded setting</span></div><div class="line">    app.CheckboxFullscreen = app.Gui-&gt;addCheckBox(</div><div class="line">            app.Settings-&gt;getSettingAsBoolean(<span class="stringliteral">&quot;fullscreen&quot;</span>),</div><div class="line">            rect&lt;s32&gt;(10,220,220,240), windowSettings, -1,</div><div class="line">            L<span class="stringliteral">&quot;Fullscreen&quot;</span>);</div><div class="line"></div><div class="line">    <span class="comment">//last but not least add save button</span></div><div class="line">    app.ButtonSave = app.Gui-&gt;addButton(</div><div class="line">            rect&lt;s32&gt;(80,250,150,270), windowSettings, 2,</div><div class="line">            L<span class="stringliteral">&quot;Save video settings&quot;</span>);</div><div class="line"></div><div class="line">    <span class="comment">//exit/cancel button</span></div><div class="line">    app.ButtonExit = app.Gui-&gt;addButton(</div><div class="line">            rect&lt;s32&gt;(160,250,240,270), windowSettings, 2,</div><div class="line">            L<span class="stringliteral">&quot;Cancel and exit&quot;</span>);</div><div class="line">}</div></div><!-- fragment --><p> The main function. Creates all objects and does the XML handling. </p><div class="fragment"><div class="line"><span class="keywordtype">int</span> main()</div><div class="line">{</div><div class="line">    <span class="comment">//create new application context</span></div><div class="line">    SAppContext app;</div><div class="line"></div><div class="line">    <span class="comment">//create device creation parameters that can get overwritten by our settings file</span></div><div class="line">    SIrrlichtCreationParameters param;</div><div class="line">    param.DriverType = EDT_SOFTWARE;</div><div class="line">    param.WindowSize.set(640,480);</div><div class="line"></div><div class="line">    <span class="comment">// Try to load config.</span></div><div class="line">    <span class="comment">// I leave it as an exercise of the reader to store the configuration in the local application data folder,</span></div><div class="line">    <span class="comment">// the only logical place to store config data for games. For all other operating systems I redirect to your manuals</span></div><div class="line">    app.Settings = <span class="keyword">new</span> SettingManager(getExampleMediaPath() + <span class="stringliteral">&quot;settings.xml&quot;</span>);</div><div class="line">    <span class="keywordflow">if</span> ( !app.Settings-&gt;load() )</div><div class="line">    {</div><div class="line">        <span class="comment">// ...</span></div><div class="line">        <span class="comment">// Here add your own exception handling, for now we continue because there are defaults set in SettingManager constructor</span></div><div class="line">        <span class="comment">// ...</span></div><div class="line">    }</div><div class="line">    <span class="keywordflow">else</span></div><div class="line">    {</div><div class="line">        <span class="comment">//settings xml loaded from disk,</span></div><div class="line"></div><div class="line">        <span class="comment">//map driversetting to driver type and test if the setting is valid</span></div><div class="line">        <span class="comment">//the DriverOptions map contains string representations mapped to to irrlicht E_DRIVER_TYPE enum</span></div><div class="line">        <span class="comment">//e.g &quot;direct3d9&quot; will become 4</span></div><div class="line">        <span class="comment">//see DriverOptions in the settingmanager class for details</span></div><div class="line">        map&lt;stringw, s32&gt;::Node* driver = app.Settings-&gt;DriverOptions.find( app.Settings-&gt;getSetting(<span class="stringliteral">&quot;driver&quot;</span>) );</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (driver)</div><div class="line">        {</div><div class="line">            <span class="keywordflow">if</span> ( irr::IrrlichtDevice::isDriverSupported( static_cast&lt;E_DRIVER_TYPE&gt;( driver-&gt;getValue() )))</div><div class="line">            {</div><div class="line">                <span class="comment">// selected driver is supported, so we use it.</span></div><div class="line">                param.DriverType = <span class="keyword">static_cast&lt;</span>E_DRIVER_TYPE<span class="keyword">&gt;</span>( driver-&gt;getValue());</div><div class="line">            }</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">//map resolution setting to dimension in a similar way as demonstrated above</span></div><div class="line">        map&lt;stringw, dimension2du&gt;::Node* res = app.Settings-&gt;ResolutionOptions.find( app.Settings-&gt;getSetting(<span class="stringliteral">&quot;resolution&quot;</span>) );</div><div class="line">        <span class="keywordflow">if</span> (res)</div><div class="line">        {</div><div class="line">            param.WindowSize = res-&gt;getValue();</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">//get fullscreen setting from config</span></div><div class="line">        param.Fullscreen = app.Settings-&gt;getSettingAsBoolean(<span class="stringliteral">&quot;fullscreen&quot;</span>);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">//create the irrlicht device using the settings</span></div><div class="line">    app.Device = createDeviceEx(param);</div><div class="line">    <span class="keywordflow">if</span> (app.Device == 0)</div><div class="line">    {</div><div class="line">        <span class="comment">// You can add your own exception handling on driver failure</span></div><div class="line">        exit(0);</div><div class="line">    }</div><div class="line"></div><div class="line">    app.Device-&gt;setWindowCaption(L<span class="stringliteral">&quot;Xmlhandling - Irrlicht engine tutorial&quot;</span>);</div><div class="line">    app.Driver  = app.Device-&gt;getVideoDriver();</div><div class="line">    app.Gui     = app.Device-&gt;getGUIEnvironment();</div><div class="line"></div><div class="line">    createSettingsDialog(app);</div><div class="line"></div><div class="line">    <span class="comment">//set event receiver so we can respond to gui events</span></div><div class="line">    MyEventReceiver receiver(app);</div><div class="line">    app.Device-&gt;setEventReceiver(&amp;receiver);</div><div class="line"></div><div class="line">    <span class="comment">//enter main loop</span></div><div class="line">    <span class="keywordflow">while</span> (!app.ShouldQuit &amp;&amp; app.Device-&gt;run())</div><div class="line">    {</div><div class="line">        <span class="keywordflow">if</span> (app.Device-&gt;isWindowActive())</div><div class="line">        {</div><div class="line">            app.Driver-&gt;beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(0,200,200,200));</div><div class="line">            app.Gui-&gt;drawAll();</div><div class="line">            app.Driver-&gt;endScene();</div><div class="line">        }</div><div class="line">        app.Device-&gt;sleep(10);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">//app destroys device in destructor</span></div><div class="line"></div><div class="line">    <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --> </div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.13-->
<!-- start footer part -->
<p>&nbsp;</p>
</body>
</html>
